use regex::Regex;
use chrono::NaiveDate;
use std::net::Ipv4Addr;

pub struct ValidateUtil;

impl ValidateUtil {
    /// 判断字符串是否合法
    pub fn is_valid_string(value: &str, min_length: Option<usize>, max_length: Option<usize>, pattern: Option<&str>) -> bool {
        if min_length.map_or(false, |min| value.len() < min) {
            return false;
        }
        if max_length.map_or(false, |max| value.len() > max) {
            return false;
        }
        if let Some(pat) = pattern {
            let re = Regex::new(pat).unwrap();
            if !re.is_match(value) {
                return false;
            }
        }
        true
    }

    /// 判断整数是否合法
    pub fn is_valid_int(value: i32, min_value: Option<i32>, max_value: Option<i32>) -> bool {
        if min_value.map_or(false, |min| value < min) {
            return false;
        }
        if max_value.map_or(false, |max| value > max) {
            return false;
        }
        true
    }

    /// 判断浮点数是否合法
    pub fn is_valid_float(value: f64, min_value: Option<f64>, max_value: Option<f64>) -> bool {
        if min_value.map_or(false, |min| value < min) {
            return false;
        }
        if max_value.map_or(false, |max| value > max) {
            return false;
        }
        true
    }

    /// 判断邮箱是否合法
    pub fn is_valid_email(value: &str) -> bool {
        let re = Regex::new(r"^[\w\.-]+@[a-zA-Z\d\.-]+\.[a-zA-Z]{2,}$").unwrap();
        re.is_match(value)
    }

    /// 判断URL是否合法
    pub fn is_valid_url(value: &str) -> bool {
        let re = Regex::new(r"^https?://[^\s/$.?#].[^\s]*$").unwrap();
        re.is_match(value)
    }

    /// 判断日期是否合法
    pub fn is_valid_date(value: &str, date_format: &str) -> bool {
        NaiveDate::parse_from_str(value, date_format).is_ok()
    }

    /// 判断MAC地址是否合法
    pub fn is_valid_mac_address(value: &str) -> bool {
        let re = Regex::new(r"^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$").unwrap();
        re.is_match(value)
    }

    /// 判断IP地址是否合法
    pub fn is_valid_ip_address(value: &str) -> bool {
        value.parse::<Ipv4Addr>().is_ok()
    }

    /// 判断信用卡号是否合法
    pub fn is_valid_credit_card(value: &str) -> bool {
        let re = Regex::new(r"^\d{16}$").unwrap();
        re.is_match(value)
    }

    /// 判断十六进制颜色值是否合法
    pub fn is_valid_hex_color(value: &str) -> bool {
        let re = Regex::new(r"^#[0-9A-Fa-f]{6}$").unwrap();
        re.is_match(value)
    }

    /// 判断车牌号是否合法（中国车牌）
    pub fn is_valid_plate_number(value: &str) -> bool {
        let re = Regex::new(r"^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼][A-Z][A-Z0-9]{5}$").unwrap();
        re.is_match(value)
    }

    /// 判断是否为二进制数
    pub fn is_valid_binary(value: &str) -> bool {
        let re = Regex::new(r"^[01]+$").unwrap();
        re.is_match(value)
    }

    /// 判断信用卡有效期是否合法
    pub fn is_valid_credit_card_expiration_date(value: &str, date_format: &str) -> bool {
        match NaiveDate::parse_from_str(value, date_format) {
            Ok(exp_date) => exp_date > chrono::Utc::today().naive_utc(),
            Err(_) => false,
        }
    }

    /// 判断是否为有效的地理坐标
    pub fn is_valid_coordinates(lat: f64, lon: f64) -> bool {
        lat >= -90.0 && lat <= 90.0 && lon >= -180.0 && lon <= 180.0
    }

    /// 判断年龄是否合法
    pub fn is_valid_age(value: i32, min_age: i32, max_age: i32) -> bool {
        value >= min_age && value <= max_age
    }

    /// 判断信用评分是否合法
    pub fn is_valid_credit_score(value: i32, min_score: i32, max_score: i32) -> bool {
        value >= min_score && value <= max_score
    }
}
